package com.springmvc.context;

import com.springmvc.anotation.AutoWired;
import com.springmvc.anotation.Controller;
import com.springmvc.anotation.Service;
import com.springmvc.exception.ContextException;
import com.springmvc.xml.XmlPaser;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Spring容器
 */
public class WebApplicationContext {

    String contextConfigLocation;
    List<String> classNameList = new ArrayList<>();

    // Spring的IOC容器
    public Map<String, Object> iocMap = new ConcurrentHashMap<>();

    public WebApplicationContext(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;
    }

    /**
     * 初始化Spring容器
     */
    public void refresh(){
        // 解析springmvc.xml配置文件，do4j解析
        String basePackage = XmlPaser.getBasePackage(contextConfigLocation.split(":")[1]);
        // 若有多个配置文件分别处理
        String[] basePackages = basePackage.split(",");
        if (basePackages.length > 0){
            for (String pack : basePackages) {
                // 扫描包
                this.excuteScanPackage(pack);
            }
        }
        System.out.println("扫包结果：" + classNameList);
        // 实例化Spring容器中的Bean
        excuteInstance();
        System.out.println("SpringIOC的容器对象：" + iocMap);
        // 实现Spring容器中和对象的注入
        excuteAutoWired();

    }

    /**
     * 扫描包
     * @param pack
     */
    public void excuteScanPackage(String pack){
        // 将com.bruce.controller中的所有.换成/
        URL url = this.getClass().getResource("/" + pack.replaceAll("\\.", "/"));
        // 获取文件路径
        String path = url.getFile();
        // 递归遍历文件夹下所有的文件
        File fileDir = new File(path);
        for (File file : fileDir.listFiles()) {
            if (file.isDirectory()){
                // 文件夹，继续扫描包
                excuteScanPackage(pack + "." + file.getName());
            }
            else{
                // 文件
                // 获取全路径 com.bruce.service.UserService
                String className = pack + "." + file.getName().replace(".class", "");
                classNameList.add(className);
            }

        }

    }

    /**
     * 实例化Spring容器的Bean对象
     */
    private void excuteInstance(){
       try {
           if (classNameList.size() == 0){
               // 没有需要扫描的实例化类
               throw new ContextException("没有实例化的class");
           }
           for (String className: classNameList) {
               // 根据给定的类名，通过反射机制加载并返回对应类的Class对象
               Class<?> aClass = Class.forName(className);
               if (aClass.isAnnotationPresent(Controller.class)){
                   String beanName = aClass.getSimpleName().substring(0, 1).toLowerCase() + aClass.getSimpleName().substring(1);
                   iocMap.put(beanName, aClass.newInstance());
               }
               else if (aClass.isAnnotationPresent(Service.class)){
                   // 获取注解，先看注解是否有默认的值
                   Service service = aClass.getAnnotation(Service.class);
                   String value = service.value();
                   if (value.equals("")){
                       // 无默认值
                       // 获取其实现的接口列表
                       Class<?>[] interfaces = aClass.getInterfaces();
                       for (Class<?> anInterface : interfaces) {
                           String beanName = anInterface.getSimpleName().substring(0, 1).toLowerCase() + anInterface.getSimpleName().substring(1);
                           iocMap.put(beanName, aClass.newInstance());
                       }
                   }
                   else{
                       // 有默认值
                       iocMap.put(value, aClass.newInstance());
                   }
               }


           }





       } catch (Exception e){
           e.printStackTrace();
       }

    }

    /**
     * 实现Spring容器中和对象的注入
     */
    private void excuteAutoWired(){
       try {
           if (iocMap.isEmpty()){
               throw new ContextException("没有找到初始化的Bean对象");
           }
           for (Map.Entry<String, Object> iocEntry : iocMap.entrySet()) {
               String key = iocEntry.getKey();
               Object value = iocEntry.getValue();
               // 获取该Class对象的所有字段（包括私有字段）
               Field[] declaredFields = value.getClass().getDeclaredFields();
               for (Field declaredField : declaredFields) {
                   // 获取每个字段上有AutoWired注解的值
                   AutoWired annotation = declaredField.getAnnotation(AutoWired.class);
                   String beanName = annotation.value();
                   if (beanName.equals("")){
                       Class<?> type = declaredField.getType();
                       beanName = type.getSimpleName().substring(0, 1).toLowerCase() + type.getSimpleName().substring(1);
                   }
                   // 设置暴力反射
                   declaredField.setAccessible(true);
                   // 属性注入，调用反射给属性赋值
                   declaredField.set(value, iocMap.get(beanName));
               }

           }
       } catch (Exception e){
           e.printStackTrace();
       }
    }
}
